using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace LINQ
{
    internal delegate void MyDelegate();

    [TestClass]
    public class Presentation
    {
        [TestMethod]
        public void Demo1_some_definitions()
        {
            var basicArray = new int[0];
            var genericList = new List<int>();
            var genericDictionary = new Dictionary<int, string>();

            Assert.IsTrue(basicArray is IEnumerable);
            Assert.IsTrue(genericList is IEnumerable);
            Assert.IsTrue(genericDictionary is IEnumerable);

            // everything to do with IEnumerable can be used with LINQ

            var ints = new[] {1, 2, 3, 4, 5};

            var intsGreaterThanOne = ints.Where(x => x > 1);
            var intsGreaterThanTwo = intsGreaterThanOne.Where(x => x > 2);
            Assert.AreEqual(3, intsGreaterThanTwo.Count());
            Assert.AreEqual(4, intsGreaterThanOne.Count());
            Assert.AreEqual(5, ints.Count());

            // linq queries are composable

            var numberOfCalls = 0;
            intsGreaterThanOne = ints.Where(x => { numberOfCalls++; return x > 1; });

            Assert.AreEqual(0, numberOfCalls);

            intsGreaterThanOne.Count();
            Assert.AreEqual(5, numberOfCalls);

            intsGreaterThanOne.Count();
            Assert.AreEqual(10, numberOfCalls);

            // deferred execution
        }

        [TestMethod]
        public void Demo2_paging_with_linq()
        {
            var ints = new[] {1, 2, 3, 4, 5, 6};

            IEnumerable<int> baseQuery = ints.Where(x => x > 0);

            int page = 2;
            int pageSize = 3;

            int total = baseQuery.Count();
            IEnumerable<int> pagedQuery = baseQuery
                .Skip((page - 1) * pageSize)
                .Take(pageSize);

            Assert.AreEqual(6, total);
            Assert.AreEqual(3, pagedQuery.Count());
        }

        [TestMethod]
        public void Demo3_projection()
        {
            IEnumerable<string> names = Student.Students.Select(x => string.Format("{0}, {1}", x.Last, x.First));

            Assert.AreEqual(12, names.Count());
            Assert.AreEqual("Omelchenko, Svetlana", names.First());

            var students = Student.Students
                .Select(x => new
                    {
                        x.Id,
                        FullName = string.Format("{0}, {1}", x.Last, x.First),
                        x.Scores
                    });

            Assert.AreEqual(12, students.Count());
            Assert.AreEqual("Omelchenko, Svetlana", students.First().FullName);
        }

        [TestMethod]
        public void Demo4_extension_methods()
        {
            int count = 0;

            var students = Student.Students
                .Each(x =>
                {
                    count++;
                    x.First = "Screw You";
                });

            Assert.AreEqual(12, count);

            IEnumerable<string> names = Student.Students.Select(x => "{0}, {1}".F(x.Last, x.First));
        }

        [TestMethod]
        public void Run_async()
        {
            Action work = () => { Thread.Sleep(3000); Console.WriteLine("hello"); };

            work.RunAsync();

            Console.WriteLine("Ran it");
            Thread.Sleep(5000);
        }
    }
}